package cn.jingyuan.swan.gw.web.security;

import cn.jingyuan.swan.cloud.oauth2.error.DefaultOAuth2ExceptionSupport;
import cn.jingyuan.swan.gw.service.AccessLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.DefaultThrowableAnalyzer;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.util.ThrowableAnalyzer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 认证处理
 */
@Slf4j
@Component
public class JsonAuthenticationEntryPoint implements AuthenticationEntryPoint {

    private final ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();

    @Resource
    private final AccessLogService accessLogService;

    public JsonAuthenticationEntryPoint(AccessLogService accessLogService) {
        this.accessLogService = accessLogService;
    }

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
        throws IOException, ServletException {
        log.debug(authException.getMessage(), authException);

        // Try to extract a SpringSecurityException from the stacktrace
        Throwable[] causeChain = throwableAnalyzer.determineCauseChain(authException);
        Exception ase = (OAuth2Exception) throwableAnalyzer.getFirstThrowableOfType(OAuth2Exception.class, causeChain);
        if (null == ase) {
            ase = authException;
        }

        accessLogService.sendLog(request, response, ase);

        DefaultOAuth2ExceptionSupport.doCommence(request, response, ase);
    }

}
